import { defineComponent, onMounted, reactive, ref } from 'vue'
import type {
  assetWorkAreaStateType,
  FormInfoMap,
  assetOverlaysArr,
  dragEndObj,
  assetNameArrItem,
  assetOverlaysObj
} from './typings'
import { ElLink, ElMessageBox, ElMessage, ElTooltip, ElScrollbar } from 'element-plus'
import Vuedraggable from 'vuedraggable' /** 可拖拽 **/
import AliIcon from '../../../../components/AliIocn' /** 阿里巴巴图标库**/

import MapToolView from '../../components/map/MapToolView' /** 地图 */

import { useStore } from 'vuex'
import EditUInfoModel from './options' /** 新增、编辑弹框 */
import ToolbarModel from './toolbarModel' /** 地图工具栏 */

import styles from '../../index.module.scss' /** 样式 */
import useVuexGetters from '~/hooks/useVuexGetters'

import type { Position } from '@turf/turf'

import { lineString, bbox, polygon, randomPoint, booleanPointInPolygon } from '@turf/turf'

export default defineComponent(function AssetWorkArea() {
  const store = useStore()
  // 定义变量
  const state = reactive<assetWorkAreaStateType>({
    list: [],
    modalVisible: false,
    // type: '', // add: '新增', update: '编辑'
    record: {},
    id: '',
    mapRef: {},
    aMapRef: {},
    areaVisible: true
  })

  // 获取租户设置的坐标
  const getCurrentTenant = useVuexGetters('user', ['userAddressInfo'])
  const userState = useVuexGetters('user', ['permission'])
  const globalState = useVuexGetters('global', ['provinceSelectList'])
  const mapToolView = ref()
  const areaInfoModelRef = ref()
  const ToolbarModelRef = ref() // 工具条
  const overlaysArr = ref<assetOverlaysArr>([])
  const assetNameArr = ref<assetNameArrItem>([]) // 所有区域名
  // 关闭工具条按钮
  const closeToolBtn = () => {
    ToolbarModelRef.value?.closeToolBtn?.()
  }

  // 区域列表行数据的点击事件, 背景高亮、地图定位到区域面
  const liOnClick = async (record: FormInfoMap, noJudgeModalVisible?: boolean) => {
    if (state.modalVisible && !noJudgeModalVisible) await handleChangeAreaInfoVisible()
    // 关闭工具条操作后才能操作
    if (
      noJudgeModalVisible &&
      ToolbarModelRef.value &&
      ToolbarModelRef.value.buttonType !== undefined
    ) {
      ElMessage({ type: 'warning', message: '请先保存图形再离开' })
      return
    }
    state.modalVisible = false // 弹框隐藏
    if (overlaysArr.value && overlaysArr.value.length > 0) {
      for (let p = 0; p < overlaysArr.value.length; p++) {
        for (let s = 0; s < overlaysArr.value[p].singlePolygon!.length; s++) {
          overlaysArr.value[p].singlePolygon![s]!.show() // 显示地图上存在的所有面数据
          overlaysArr.value[p].textArr![s]!.show() // 显示地图上文本数据
        }
      }
    }
    if (record) {
      state.id = state?.id === record.id ? '' : record.id! // '!'是断言的写法,将从值域中排除 null 和 undefined.
      // 地图缩放
      if (JSON.stringify(record.phase) !== '"{}"') {
        const getBoundsData = record.phase ? JSON.parse(record.phase!).coordinates : []
        const polygon_ = polygonMapData(getBoundsData, '', '', record.width ? record.width! : 1)
        let centerPoint = []
        if (polygon_ && polygon_.getPath()?.length > 1) {
          let pathFirst = null
          if (polygon_.getPath()[0][0].length > 2) {
            pathFirst = polygon_.getPath()[0][0]
          } else {
            pathFirst = polygon_.getPath()[0]
          }
          let lngCount = 0
          let latCount = 0
          for (let p = 0; p < pathFirst.length; p++) {
            lngCount += pathFirst[p].lng
            latCount += pathFirst[p].lat
          }
          centerPoint = [lngCount / pathFirst.length, latCount / pathFirst.length]
        } else {
          centerPoint = [
            polygon_.getBounds()?.getCenter().lng,
            polygon_.getBounds()?.getCenter().lat
          ]
        }

        mapToolView.value.mapRef.setZoomAndCenter(13, centerPoint, false, 100)
        // mapToolView.value.mapRef.setCenter(centerPoint)
        // mapToolView.value.mapRef.setZoom(13)
      }
    }
  }

  // 随机获取地图面中包含的点
  const handleGetMapRandomPoint = (
    lineStringData: number[],
    onePolygonData: number[]
  ): [number, number] => {
    const turfLineString = lineString(lineStringData as unknown as Position[])
    const turfBbox = bbox(turfLineString)
    const turfPolygon = polygon(onePolygonData as unknown as Position[][])
    let turfRandomPoint = randomPoint(1, { bbox: turfBbox })
    while (!booleanPointInPolygon(turfRandomPoint.features[0], turfPolygon)) {
      turfRandomPoint = randomPoint(1, { bbox: turfBbox })
    }
    return turfRandomPoint.features[0].geometry.coordinates as [number, number]
  }

  // 渲染多面
  const renderPolygon = () => {
    const polygons_: any = []
    if (!mapToolView.value.mapRef) return
    // 判断地图是否加载完成
    mapToolView.value.mapRef.clearMap()
    if (state.list && state.list.length > 0) {
      overlaysArr.value = []
      assetNameArr.value = []
      for (let p = 0; p < state.list.length; p++) {
        assetNameArr.value.push({ name: state.list[p].name })
        const singlePolygon = []
        const textArr = []
        let fillOpacity_ = 1
        let strokeOpacity_ = 1
        if (state.list[p].backColor && state.list[p].backColor!.length > 7) {
          fillOpacity_ = Number(state.list[p].backColor?.split(',')[3].split(')')[0])
        }
        if (state.list[p].bordeColor && state.list[p].bordeColor!.length > 7) {
          strokeOpacity_ = Number(state.list[p].bordeColor?.split(',')[3].split(')')[0])
        }
        // 判断是否存在空间数据
        const polygonPattern = polygonMapData(
          JSON.parse(state.list[p].phase?.length ? state.list[p].phase! : '{}').coordinates || [], // 面的空间数据
          state.list[p].bordeColor!, // 线颜色
          state.list[p].backColor!, // 填充色
          state.list[p].width ? state.list[p].width! : 1, // 线宽
          fillOpacity_,
          strokeOpacity_
        )

        polygons_.push(polygonPattern)
        singlePolygon.push(polygonPattern)
        // 创建纯文本标记
        if (polygonPattern) {
          let centerPoint: any = []

          const phaseData = JSON.parse(state.list[p].phase! || '{}')

          try {
            if (!state.list[p].centerPoint) throw new Error()
            centerPoint = JSON.parse(state.list[p].centerPoint!)
          } catch (error) {
            if (phaseData?.type === 'Polygon') {
              centerPoint = handleGetMapRandomPoint(phaseData.coordinates[0], phaseData.coordinates)
            } else if (phaseData?.type === 'MultiPolygon') {
              centerPoint = handleGetMapRandomPoint(
                phaseData.coordinates[0][0],
                phaseData.coordinates[0]
              )
            }
          }

          const text = new mapToolView.value.aMapRef.Text({
            map: mapToolView.value.mapRef,
            text: `
              <section class="area-name">${state.list[p].name}</section>
              <section class="area-total">
                面积：${state.list[p].areaTotal ?? 0}㎡
              </section>
            `,
            // text: `${state.list[p].name}<br/>${
            //   state.list[p].areaTotal ? `${state.list[p].areaTotal}㎡` : '0㎡'
            // }`,
            anchor: 'center', // 设置文本标记锚点,
            bubble: true,
            draggable: false,
            // style: {
            //   'background-color': 'rgba(165, 42, 42, 0)',
            //   'border-width': 0,
            //   'text-align': 'center',
            //   'font-size': '14px',
            //   color: 'black'
            // },
            position: centerPoint?.length ? centerPoint : undefined
          })
          // text.setMap(mapToolView.value.mapRef)
          textArr.push(text)
          overlaysArr.value.push({
            id: state.list[p].id,
            polygon: polygonPattern,
            text,
            name: state.list[p].name,
            singlePolygon,
            textArr
          })

          const obj: { [key: string]: boolean } = {}
          overlaysArr.value = overlaysArr.value.reduce<assetOverlaysObj[]>((item, next: any) => {
            if (!obj[next.id!]) {
              item.push(next)
              obj[next.id!] = true
            }
            return item
          }, [])
        }
        // }
        mapToolView.value.mapRef.add(polygons_)
        mapToolView.value.mapRef.setFitView(polygons_, true) // 地图自适应
      }
    } else {
      mapToolView.value.mapRef.setZoomAndCenter(
        13,
        [
          parseFloat(getCurrentTenant.userAddressInfo.value.lon),
          parseFloat(getCurrentTenant.userAddressInfo.value.lat)
        ],
        false,
        100
      )
    }
  }

  // 面数据结构
  const polygonMapData = (
    polygonArr: (number | string)[][],
    strokeColor: string,
    fillColor: string,
    strokeWeight: number,
    fillOpacity_?: number,
    strokeOpacity_?: number
  ) => {
    return new mapToolView.value.aMapRef.Polygon({
      map: mapToolView.value.mapRef,
      path: polygonArr?.length ? polygonArr : undefined, // 设置多边形边界路径，面空间数据
      strokeColor, // 线颜色
      fillColor, // 填充色
      strokeWeight, // 线宽
      fillOpacity: fillOpacity_,
      strokeOpacity: strokeOpacity_,
      zIndex: 1,
      bubble: true
    })
  }

  // 新增、编辑按钮事件
  const handleEdit = async (
    e: Event,
    type: assetWorkAreaStateType['type'],
    record?: FormInfoMap
  ) => {
    e.stopPropagation() // 阻止点击事件冒泡
    // 弹框提示 是否保存后再切换
    if (state.modalVisible && state.record?.id !== record?.id) await handleChangeAreaInfoVisible()
    liOnClick(record!, true) // 点击区域列表事件
    // 关闭工具条操作后才能操作, 提示在liOnClick中已给, 故此处直接跳出
    if (ToolbarModelRef.value && ToolbarModelRef.value.buttonType !== undefined) {
      return
    }
    if (type === 'add') {
      // 新增操作
      state.id = '' // 去掉选中的高亮行
      state.record = {}
      if (overlaysArr.value && overlaysArr.value.length > 0) {
        for (let p = 0; p < overlaysArr.value.length; p++) {
          // 存在多面的情况
          for (let s = 0; s < overlaysArr.value[p].singlePolygon!.length; s++) {
            overlaysArr.value[p].singlePolygon![s]!.hide() // 隐藏地图上存在的所有面数据
            overlaysArr.value[p].textArr![s]!.hide() // 隐藏地图上文本数据
          }
        }
      }
      state.modalVisible = true
      store.commit('assetWorkArea/SET_POLYGON_INFO', {
        type: 'addPolygon'
      })
    } else {
      // 编辑操作
      if (overlaysArr.value && overlaysArr.value.length > 0) {
        for (let p = 0; p < overlaysArr.value.length; p++) {
          for (let s = 0; s < overlaysArr.value[p].singlePolygon!.length; s++) {
            overlaysArr.value[p].singlePolygon![s]!.show() // 显示地图上存在的所有面数据
            overlaysArr.value[p].textArr![s]!.show() // 显示地图上文本数据
          }
        }
      }
      if (!(state.record?.id !== record?.id && state.record?.id)) {
        state.modalVisible = !state.modalVisible // 弹框是否显示
      } else {
        // handleCancel(record!)
        state.modalVisible = true
      }
      store.commit('assetWorkArea/SET_POLYGON_INFO', {
        type: 'editPolygon'
      })
      state.record = record!
    }
    state.type = type // 弹框类型，是新增还是编辑操作的弹框
  }

  // 新增、编辑子组件的取消按钮回调事件
  const handleCancel = async () => {
    state.modalVisible = false // 弹框是否显示
    state.record = {}

    //  关闭时并清空弹框类型
    state.type = undefined

    closeToolBtn()

    // if (params && state.type !== 'add' && overlaysArr.value) {
    //   for (let d = 0; d < overlaysArr.value.length; d++) {
    //     if (overlaysArr.value[d].id === state.record.id) {
    //       // 修改地图上被选中的不规则面的属性
    //       for (let t = 0; t < overlaysArr.value[d].singlePolygon!.length; t++) {
    //         (overlaysArr.value[d].singlePolygon![t] as any).setOptions({
    //           strokeColor: state.record.bordeColor, // 线颜色
    //           fillColor: state.record.backColor, // 填充色
    //           strokeWeight: state.record.width // 线宽
    //         })
    //       }
    //     }
    //   }
    // }
    await initList() // 刷新列表
  }

  // 新增/编辑时, 地图上实时更新面的属性
  const dynamicSurface = (params: FormInfoMap) => {
    for (let d = 0; d < overlaysArr.value.length; d++) {
      if (overlaysArr.value[d].id === params.id) {
        (overlaysArr.value[d].polygon as any).setOptions({
          strokeColor: params.bordeColor, // 线颜色
          fillColor: params.backColor, // 填充色
          strokeWeight: params.width // 线宽
        })
      }
    }
  }

  // 判断是否开启编辑区域弹框开启则让其选择二次确认
  const handleChangeAreaInfoVisible = async () => {
    await ElMessageBox.confirm('先保存修改的图形再离开吗？', '确认提示', {
      type: 'warning',
      closeOnClickModal: false, // 点遮罩层不关弹窗
      draggable: true // 可拖拽
    })
      .then(async () => {
        await areaInfoModelRef.value.submitAreaForm()
      })
      .catch(async () => {
        await handleCancel()
      })
  }

  // 删除按钮事件
  const handleOpenDeleteConfirm = (record: FormInfoMap) => {
    // 关闭工具条操作后才能操作, 提示在liOnClick中已给, 故此处直接跳出
    if (ToolbarModelRef.value && ToolbarModelRef.value.buttonType !== undefined) {
      return
    }

    const params = {
      ids: record?.id || 0 // 接口参数
    }
    ElMessageBox.confirm('确定删除该数据吗?（删除后不可恢复，是否确认删除）', {
      buttonSize: 'small',
      type: 'warning'
    })
      .then(async () => {
        await store.dispatch('assetWorkArea/DelateWorkArea', params).then((res: any) => {
          if (res?.code === 200) {
            ElMessage({ type: 'success', message: '操作成功' })
            initList() // 刷新区域列表
          }
        })
      })
      .catch(() => {
        state.type = undefined
        state.modalVisible = false
        initList()
        // handleCancel()
      })
  }

  // 初始化区域列表数据
  const initList = async () => {
    const res = await store.dispatch('assetWorkArea/GetAreaList', Object.assign({}))
    if (res?.code === 200) {
      state.list = res.data
      if (state.type === 'add') {
        // 新增操作时  新增的数据高亮显示
        liOnClick(state.list[0])
      }

      renderPolygon() // 重新渲染地图上的区域

      // mapToolView.value.mapRef.setFitView() // 地图自动适配到指定视野范围
    }
  }

  // 初始化
  onMounted(async () => {
    // await initList() // 初始化区域列表数据
    // 获取省市区下拉列表
    if (!globalState?.provinceSelectList?.value?.length) {
      await store.dispatch('global/GetRegionSelectTreeList')
    }
  })

  // 表格拖拽后的排序事件
  const dragEndHandle = async (obj: dragEndObj & { newIndex: number; oldIndex: number }) => {
    // 联合类型
    if (obj.newIndex !== obj.oldIndex) {
      const newIndex_ = obj.newIndex // 拖拽后的下标sort
      const params = { areaId: obj.item?._underlying_vm_.id, sort: newIndex_ }
      // 接口调用
      const res = await store.dispatch('assetWorkArea/UpdateSortWorkArea', params)
      if (res?.code === 200) {
        ElMessage({ type: 'success', message: '排序成功' })
      }
    }
  }

  return () => (
    <section class={styles.sessionDom}>
      <MapToolView id={styles['map-init']} clickon ref={mapToolView} initCallback={initList} />

      {state.areaVisible && (
        <div class={styles.areaDom}>
          <div class={styles.areaTitle}>
            <div class={styles.lineTxt}></div>区域列表
            <div class={styles.areaAddIcon}>
              {userState.permission.value.has('assets_workarea_add') && (
                <ElLink
                  type="primary"
                  underline={false}
                  onClick={(e: Event) => handleEdit(e, 'add')}
                >
                  <AliIcon type="icon-xinzeng" />
                </ElLink>
              )}
            </div>
          </div>
          <div class={styles.app}>
            <ElScrollbar class={styles['asset-area-scrollbar']}>
              <Vuedraggable
                v-model={state.list}
                itemKey="prop"
                tag="ul"
                class={styles.ulstyle}
                {...{ onEnd: dragEndHandle }}
                v-slots={{
                  item: ({ element: item }: { element: FormInfoMap }) => (
                    <li
                      key={item?.id}
                      onClick={() => liOnClick(item)}
                      class={item.id === state.id ? styles.hightLi : ''}
                    >
                      <ElTooltip
                        placement="top"
                        content={`${item?.name}  ${item?.areaTotal || 0}㎡`}
                      >
                        <div>
                          <div class={styles.hightIcon}>
                            <AliIcon type="icon-tuodongtiaozhengshunxu" />
                          </div>
                          <span class={styles.areaTxt}>{item?.name}</span>
                          <label class={styles.labtxt}>面积：{item?.areaTotal || 0}㎡ </label>
                          <div class={styles.iconDom}>
                            {userState.permission.value.has('assets_workarea_update') && (
                              <ElLink
                                underline={false}
                                type="primary"
                                onClick={(e: Event) => handleEdit(e, 'update', item)}
                              >
                                <AliIcon type="icon-bianji" />
                              </ElLink>
                            )}
                            &nbsp;
                            {userState.permission.value.has('assets_workarea_remove') && (
                              <ElLink
                                underline={false}
                                type="primary"
                                onClick={() => handleOpenDeleteConfirm(item)}
                              >
                                <AliIcon type="icon-shanchu" />
                              </ElLink>
                            )}
                          </div>
                        </div>
                      </ElTooltip>
                    </li>
                  )
                }}
              />
            </ElScrollbar>
            <div class="scrollbar"></div>
          </div>
        </div>
      )}
      {state.modalVisible && (
        <EditUInfoModel
          ref={areaInfoModelRef}
          visible={state.modalVisible}
          type={state.type}
          record={state.record}
          mapToolView={mapToolView.value}
          overlaysArr={overlaysArr.value}
          activeFullScreen={!state.areaVisible}
          buttonType={ToolbarModelRef.value} // 工具条的数据 取按钮类型
          assetNameArr={assetNameArr.value} // 区域名
          cancel={() => handleCancel()}
          getMapRandomPoint={handleGetMapRandomPoint}
          closeToolBtn={() => closeToolBtn()} // 关闭工具条操作
          dynamicSurface={(params: FormInfoMap) => dynamicSurface(params)} // 地图上实时更新面的属性
        />
      )}

      {state.modalVisible && (
        <ToolbarModel
          ref={ToolbarModelRef}
          visible={state.modalVisible}
          type={state.type}
          record={state.record}
          mapToolView={mapToolView.value}
          activeFullScreen={!state.areaVisible}
          overlaysArr={overlaysArr.value}
          cancel={() => handleCancel()}
          getMapRandomPoint={handleGetMapRandomPoint}
          changeFullScreen={() => {
            state.areaVisible = !state.areaVisible
          }}
        />
      )}
    </section>
  )
})
